package athabasca.ca.util;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.InputMismatchException;
import java.util.Scanner;

import athabasca.ca.dao.UserDAO;
import athabasca.ca.model.User;

public class Main
{	
	private enum Birthday
	{ 
		DAY( 0 ), MONTH( 1 ), YEAR( 2 );
		private int value;
		
		private Birthday( int value )
		{
			this.value = value;
		}
		
		public int Value( )
		{
			return value;
		}
	};
	
	public static void main( String[] args )
	{
		try
		{
			postgreSQL.postgreSQLConn( );
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		
		Scanner scanner = new Scanner( System.in ) ;
		String input = "";
		do
		{
			//clearConsole( );
			System.out.println( "Select your option:\n" + 
					"[C]reate - for User insertion\n" +
					"[R]etrieve - for User selection\n" +
					"[U]pdate - for User information saving\n" +
					"[D]elete - for User information removal\n" +
					"[Q]uit - for exiting the application\n");
			
			input = scanner.next( );
			System.out.println( "------------------------------------------- \n\n" );
			
			handleInput( input, scanner );
		}while( input.compareTo( "Q" ) != 0 && input.compareTo( "q" ) != 0 );
		
		scanner.close( );
		
		System.exit( 0 );

	}
	
	private static void handleInput( String input, Scanner scanner )
	{
		switch( input )
		{
			case "C":
			case "c":
			{
				userCreation( scanner );
			}
			break;
			
			case "R":
			case "r":
			{
				userRetrieval( scanner );
			}
			break;
			
			case "U":
			case "u":
			{
				try 
				{
					userUpdate( scanner );
				} 
				catch (Exception e)
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			break;
			
			case "D":
			case "d":
			{
				try
				{
					userDelete( scanner );
				}
				catch (Exception e)
				{
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			break;
			
			case "Q":
			case "q":
			{
				System.out.println( "Application exit..." );
			}
			break;
			
			default:
			{
				System.err.println( "WARNING: Invalid command!" );
			}
			break;
		}
	}

	private static void userCreation( Scanner scanner )
	{
		User user = new User( );
		
		System.out.println( "C: User insertion\n" );
		System.out.println( "Insert user information... " );
		
		System.out.println( "ID: " );
		if( scanner.hasNextBigInteger( ) )
		{
			user.setUserId( scanner.nextLong( ) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		System.out.println( "Password: " );
		if( scanner.hasNext( ) )
		{
			user.setPassword( scanner.next( ) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		System.out.println( "First Name: " );
		if( scanner.hasNext( ) )
		{
			user.setFirstName( scanner.next( ) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		System.out.println( "Last Name: " );
		if( scanner.hasNext( ) )
		{
			user.setLastName( scanner.next( ) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		System.out.println( "Birthday: " );
		if( scanner.hasNext( ) )
		{
//			String[] dateFields = scanner.next( ).split( "/" );
//			Calendar birthday = Calendar.getInstance( );
//			birthday.set( 	Integer.parseInt( dateFields[ Birthday.DAY.Value( ) ] ),
//							Integer.parseInt( dateFields[ Birthday.MONTH.Value( ) ] ),
//							Integer.parseInt( dateFields[ Birthday.YEAR.Value( )  ] ) );
			user.setBirthday( scanner.next ( ) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		int i;
		ArrayList<String> phones = new ArrayList<String> ( ); 
		System.out.println( "Number of phones: " );
		if( scanner.hasNextBigInteger( ) )
		{
			int numberOfPhones = scanner.nextInt( );
			for( i = 0; i < numberOfPhones; ++i )
			{
				System.out.println( "Phone " + ( i + 1 ) + ": " );
				if( scanner.hasNext( ) )
				{
					phones.add ( scanner.next( ) );
				}
				else
				{
					System.err.println( "ERROR: Invalid field!" );
					System.exit( 0 );
				}
			}
			
			user.addTelephones( ( String[ ] ) phones.toArray( new String[ phones.size( ) ] ) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		ArrayList<String> emails = new ArrayList<String>( ); 
		System.out.println( "Number of emails: " );
		if( scanner.hasNextBigInteger( ) )
		{
			int numberOfEmails = scanner.nextInt( );
			for( i = 0; i < numberOfEmails; ++i )
			{
				System.out.println( "Email " + ( i + 1 ) + ": " );
				if( scanner.hasNext( ) )
				{
					emails.add( scanner.next( ) );
				}
				else
				{
					System.err.println( "ERROR: Invalid field!" );
					System.exit( 0 );
				}
			}
			
			user.addEmails( ( String[ ] ) emails.toArray( new String[ emails.size( ) ]) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		System.out.println( "Other preferences (type everything and press enter): " );
		if( scanner.hasNextLine( ) )
		{
			user.setOtherPreferences( scanner.next( ) );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		System.out.println( "\n\n" + user.toString( ) );
		scanner.reset( );
		
//		V2_user insertUser = new V2_user();
		
		// *The method keeps returning a false value for some reason.
		// The create method seems to work well however when using a different test class
		int isTrue;
		try
		{
//			isTrue = insertUser.create(user);
			isTrue = UserDAO.create ( user );
			if (isTrue > 0) 
			{
				System.out.println("Creation was a success!");
			}
			else if (isTrue <= 0)
			{
				System.out.println("User creation failed!");
			}
		}
		catch (Exception e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		scanner.reset( );
	}

	/**
	 * @param scanner
	 */
	private static void userRetrieval( Scanner scanner )
	{
		System.out.println( "R: User retrieval\n" );
		System.out.println( "Insert information filters...[press '-' + enter if you do not want to use the presented field]" );
		
		//capacity = number of user attributes but two (phones and emails)
		Hashtable<String, Object> filters = new Hashtable<String, Object>( 6 );
		ArrayList<String> emails = new ArrayList<String>( );
		ArrayList<String> phones = new ArrayList<String>( );
		
		System.out.println( "ID: " );
		if( scanner.hasNext( ) && !scanner.hasNext( "-" ) )
		{
			try
			{
				filters.put( "userID" ,  scanner.nextLong( ) );
			}
			catch(InputMismatchException e)
			{
				System.err.println( "ERROR: Invalid field! " + e.getMessage( ) );
				System.exit( 0 );
			}
		}
		else if ( scanner.next( "-" ) != null );
			
		
		System.out.println( "Password: " );
		if( scanner.hasNext( ) && !scanner.hasNext( "-" ) )
		{
			try
			{
				filters.put( "password" ,  scanner.next( ) );
			}
			catch(InputMismatchException e)
			{
				System.err.println( "ERROR: Invalid field! " + e.getMessage( ) );
				System.exit( 0 );
			}
		}
		else if ( scanner.next( "-" ) != null );
		
		System.out.println( "First name: " );
		if( scanner.hasNext( ) && !scanner.hasNext( "-" ) )
		{
			try
			{
				filters.put( "firstName" ,  scanner.next( ) );
			}
			catch(InputMismatchException e)
			{
				System.err.println( "ERROR: Invalid field! " + e.getMessage( ) );
				System.exit( 0 );
			}
		}
		else if ( scanner.next( "-" ) != null );
		
		System.out.println( "Last name: " );
		if( scanner.hasNext( ) && !scanner.hasNext( "-" ) )
		{
			try
			{
				filters.put( "lastName" ,  scanner.next( ) );
			}
			catch(InputMismatchException e)
			{
				System.err.println( "ERROR: Invalid field! " + e.getMessage( ) );
				System.exit( 0 );
			}
		}
		else if ( scanner.next( "-" ) != null );
		
		System.out.println( "Birthday: " );
		if( scanner.hasNext( ) && !scanner.hasNext( "-" ) )
		{
			try
			{
				String[] dateFields = scanner.next( ).split( "/" );
				Calendar birthday = Calendar.getInstance( );
				birthday.set( 	Integer.parseInt( dateFields[ Birthday.DAY.Value( ) ] ),
								Integer.parseInt( dateFields[ Birthday.MONTH.Value( ) ] ),
								Integer.parseInt( dateFields[ Birthday.YEAR.Value( )  ] ) );
				
				filters.put( "birthday" ,  birthday );
			}
			catch(InputMismatchException e)
			{
				System.err.println( "ERROR: Invalid field! " + e.getMessage( ) );
				System.exit( 0 );
			}
		}
		else if ( scanner.next( "-" ) != null );
		
		int i;
		int numberOfEmails = 0; 
		System.out.println( "Number of emails: " );
		if( scanner.hasNextBigInteger( ) && !scanner.hasNext( "-" ) )
		{
			numberOfEmails = scanner.nextInt( );
			for( i = 0; i < numberOfEmails; ++i )
			{
				System.out.println( "Email " + ( i + 1 ) + ": " );
				if( scanner.hasNext( ) )
				{
					emails.add( scanner.next( ) );
				}
				else
				{
					System.err.println( "ERROR: Invalid field!" );
					System.exit( 0 );
				}
			}
			
			if ( numberOfEmails > 0 )
				filters.put( "emails", ( String[] ) emails.toArray( ) );
		}
		
		int numberOfPhones = 0; 
		System.out.println( "Number of phones: " );
		if( scanner.hasNextBigInteger( ) && !scanner.hasNext( "-" ) )
		{
			numberOfPhones = scanner.nextInt( );
			for(i = 0; i < numberOfPhones; ++i )
			{
				System.out.println( "Telephone " + ( i + 1 ) + ": " );
				if( scanner.hasNext( ) )
				{
					phones.add( scanner.next( ) );
				}
				else
				{
					System.err.println( "ERROR: Invalid field!" );
					System.exit( 0 );
				}
			}
			
			if ( numberOfPhones > 0)
				filters.put( "telephones", ( String[ ] ) phones.toArray( ) );
		}
		
		Enumeration<String> keys = filters.keys( );
		while( keys.hasMoreElements( ) )
		{
			String key = keys.nextElement( );
			switch( key )
			{
				case "telephones":
				case "emails":
				{
					System.out.println( key );
					for(String element : (String[]) filters.get( key ))
					{
						System.out.println( element );
					}
				}
				break;
				
				default:
				{
					System.out.println( key + " " + filters.get( key ).toString( ) );
				}
				break;
			}
		}
		
		User[] specificUsers = null;
		try 
		{
			specificUsers = UserDAO.select( filters );
			for ( User specUser : specificUsers)
			{
				System.out.println("Id: " + specUser.getUserId());
				System.out.println("First Name: " + specUser.getFirstName());
				System.out.println("Last Name: " + specUser.getLastName());
				System.out.println("Birthday: " + specUser.getBirthday());
				System.out.println("Other Preferences: " + specUser.getOtherPreferences());
				
				for ( String telephone : specUser.getTelephones( ) )
				{
					System.out.println("Telephone: " + telephone );
				}
				
				for ( String email : specUser.getEmails( ) )
				{
					System.out.println("Email: " + email );
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
			System.err.println("Could not find user!");
		}
		
		
	}
		
	private static void userRetrieval_Mohamed( Scanner scanner ) throws Exception
	{
//		V2_user selectUser = new V2_user();
		long selection = 0;
		
		System.out.println( "R: User selection\n" );
		System.out.println( "Insert user id... " );
		
		if( scanner.hasNextBigInteger( ) )
		{
			selection = scanner.nextLong( );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
//		User[] specificUsers = selectUser.select(selection);
		//Is it really needed to instantiate an object? We could just do like this
		//(specifying to just one user)
		User specificUser = UserDAO.select( selection );
		
		if ( specificUser != null )
		{
			System.out.println("Id: " + specificUser.getUserId());
			System.out.println("First Name: " + specificUser.getFirstName());
			System.out.println("Last Name: " + specificUser.getLastName());
			System.out.println("Birthday: " + specificUser.getBirthday());
			System.out.println("Other Preferences: " + specificUser.getOtherPreferences());
			
			for ( String telephone : specificUser.getTelephones( ) ) {
				System.out.println("Telephone: " + telephone );
			}
			
			for ( String email : specificUser.getEmails( ) ) {
				System.out.println("Email: " + email );
			}
		} else {
			System.err.println("Could not find user!");
		}
		
		scanner.reset();
	}
	
	private static void userUpdate( Scanner scanner ) throws Exception
	{
		UserDAO updateUser = new UserDAO();
		long selection = 0;
		Hashtable<String, Object> args = new Hashtable<String, Object> ( );
		
		String f_name = null;
		String l_name = null;
		String b_day = null;
		String tele = null;
		String email = null;
		String other = null;
		
		System.out.println( "U: User update\n" );
		System.out.println( "Insert user id... " );
		
		if( scanner.hasNextBigInteger( ) )
		{
			selection = scanner.nextLong( );
			scanner.reset();
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		System.out.println("Please enter update information:");
		
		if (scanner.hasNextLine()) {
			f_name = scanner.nextLine();
			l_name = scanner.nextLine();
			b_day = scanner.nextLine();
			tele = scanner.nextLine();
			email = scanner.nextLine();
			other = scanner.nextLine();
		} else {
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		args.put("first_name", f_name);
		args.put("last_name", l_name);
		args.put("birthday", b_day);
		args.put("telephone", tele);
		args.put("email", email);
		args.put("other_preferences", other);
		
		/**
		 * Does it have to be instantiated? Why not use static method directly?
		 * */
		boolean isTrue = updateUser.update(selection, args);
		
		if (isTrue == true) {
			System.out.println("User has been updated!");
		} else {
			System.out.println("User was not updated!");
		}
		
		scanner.reset();
	}
	
	private static void userDelete( Scanner scanner ) throws Exception
	{
		long selection = 0;
		String password = "";
		
		System.out.println( "D: User deletion\n" );
		System.out.println( "Insert user id... " );
		
		if( scanner.hasNextBigInteger( ) )
		{
			selection = scanner.nextLong( );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		if( scanner.hasNextBigInteger ( ) )
		{
			password = scanner.next ( );
		}
		else
		{
			System.err.println( "ERROR: Invalid field!" );
			System.exit( 0 );
		}
		
		User deletedUser = new User ( selection, password );
		
		boolean isTrue = UserDAO.delete( deletedUser.getUserId(), password );
		
		if (isTrue == true) {
			System.out.println("User has been deleted!");
		} else {
			System.out.println("User was not found!");
		}
		
		scanner.reset();
	}
	/* this method does not work
	private static void clearConsole( )
	{
	    try
	    {
	        String os = System.getProperty( "os.name" );

	        if ( os.contains( "Windows" ) )
	        {
	            Runtime.getRuntime( ).exec( "cls" );
	        }
	        else
	        {
	            Runtime.getRuntime( ).exec( "clear" );
	        }
	    }
	    catch ( Exception exception )
	    {
	        System.out.println( exception.getMessage( ) );
	    }
	}
	*/

}




